package com.adcc.foc.task;

import com.adcc.foc.config.AppConfig;
import com.adcc.foc.domain.LoginErrorRecord;
import com.adcc.foc.utils.Log;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;


@Component
@EnableScheduling
public class LoginRefreshTimer implements SchedulingConfigurer {

    public static List<LoginErrorRecord> list = Collections.synchronizedList(new ArrayList<LoginErrorRecord>());

    @Resource
    private AppConfig appConfig;

    private static int staticTime;

    private static int limitCount;


    @PostConstruct
    public void init() {
        staticTime = appConfig.getLimitTime();
        limitCount = appConfig.getLimitCount();
    }
    public static LoginErrorRecord getByMask(String mask){
        LoginErrorRecord record_ = null;
        try{
            for (LoginErrorRecord record : list) {
                if (record.getLoginMask().equals(mask)) {
                    record_ = record;
                }
            }
        }catch (Exception e){

        }
        return  record_;
    }

    public static void removeByMask(String mask){
        List<LoginErrorRecord> records = new ArrayList<>();
        try {
            for (LoginErrorRecord record : list) {
                if (!record.getLoginMask().equals(mask)) {
                    records.add(record);
                }
            }
            list = records;
        } catch (Exception e) {
            Log.error(ExceptionUtils.getFullStackTrace(e), LoginRefreshTimer.class);
        }
    }

    public static void save(String mask){
        try {
            boolean isHave = false;

            for (LoginErrorRecord record : list) {
                if (record.getLoginMask().equals(mask)) {
                    isHave = true;
                    int errorCount = record.getErrorCount();
                    errorCount++;
                    record.setErrorCount(errorCount);
                    record.setUpdateTime(new Date());
                    if (errorCount > limitCount) {
                        record.setWaitingTime(staticTime);
                    }
                }
            }
            if (!isHave) {
                LoginErrorRecord loginErrorRecord = new LoginErrorRecord();
                loginErrorRecord.setLoginMask(mask);
                loginErrorRecord.setUpdateTime(new Date());
                loginErrorRecord.setErrorCount(1);
                list.add(loginErrorRecord);
            }
        } catch (Exception e) {
            Log.error(ExceptionUtils.getFullStackTrace(e), LoginRefreshTimer.class);
        }
    }

    /**
     * 记录错误登录信息
     * @param ip
     * @param userName
     */
    public static void maskRecord(String ip,String userName){
        save(ip);
        save(userName);
    }

    /**
     * 移除记录
     * @param ip
     * @param userName
     */
    public static void removeMask(String ip,String userName){
        removeByMask(ip);
        removeByMask(userName);
    }

    public static Map<String,Object> isLock(String ip, String userName){
        Map<String,Object> map = new HashMap<>();
        LoginErrorRecord ipRecord = getByMask(ip);
        LoginErrorRecord userNameRecord = getByMask(userName);
        if(ipRecord == null && userNameRecord ==null){
            map.put("isLock",false);
            return map;
        }
        if(ipRecord == null){
            map.put("isLock", userNameRecord.getErrorCount()>limitCount);
            map.put("waitTime", userNameRecord.getWaitingTime());
            return map;
        }
        if(userNameRecord == null){
            map.put("isLock", ipRecord.getErrorCount()>limitCount);
            map.put("waitTime", ipRecord.getWaitingTime());
            return map;
        }
        boolean isLock = ipRecord.getErrorCount()>limitCount || userNameRecord.getErrorCount()>limitCount;
        map.put("isLock", isLock);
        map.put("waitTime", ipRecord.getWaitingTime()> userNameRecord.getWaitingTime() ? ipRecord.getWaitingTime():userNameRecord.getWaitingTime());
        return map;

    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
       Runnable task  = new Runnable() {
           @Override
           public void run() {
               try{
                   if (list.size() != 0) {
                       Date date = new Date();
                       Iterator<LoginErrorRecord> it = list.iterator();
                       while (it.hasNext()) {
                           LoginErrorRecord record = it.next();
                           if (Math.abs(date.getTime() - record.getUpdateTime().getTime()) > appConfig.getLimitTime() * 1000 * 60) {
                               it.remove();
                           } else {
                               if (record.getErrorCount() > appConfig.getLimitCount()) {
                                   record.setWaitingTime( appConfig.getLimitTime() - (int) (Math.abs(date.getTime() - record.getUpdateTime().getTime()) / (1000 * 60)));
                               }
                           }
                       }

                   }
               }catch (Exception e){
                   Log.error(ExceptionUtils.getFullStackTrace(e), LoginRefreshTimer.class);
               }
           }
       };
        Trigger trigger = new Trigger() {
            @Override
            public Date nextExecutionTime(TriggerContext triggerContext) {
                String cron = appConfig.getCron() == null || appConfig.getCron().equals("''") || appConfig.getCron().equals("")? "*/10 * * * * ?" : appConfig.getCron();
                CronTrigger cronTrigger = new CronTrigger(cron);
                Date nextExecTime = cronTrigger.nextExecutionTime(triggerContext);
                return nextExecTime;
            }
        };
        scheduledTaskRegistrar.addTriggerTask(task,trigger);
    }
}
